/**
 * @brief 责任链模式。
 * 
 * @author 宋炜
 * @version 1.0
 * @date 2023-4-27~2024-8-6
 */

#pragma once

#include <list>
#include <type_traits>
#include <mutex>

namespace rspsprivate__
{
	struct respItfc__{};
}

#define DECLARE_RESPLINK_ITFC( name )                   	\
    struct name :public rspsprivate__::respItfc__ {         \
    virtual ~name(){}

// 如果不使用回调函数调用的时候，name必须声明为operation
#define RESPLINK_ITFC_MTD( name , ... )   virtual bool name(  __VA_ARGS__ ) = 0;

#define END_DECLARE_RESPLINK_ITFC()   };
	
#define DECLARE_RESPLINK_ITFC_DEFAULT( name , ...)		\
DECLARE_RESPLINK_ITFC( name ) 							\
RESPLINK_ITFC_MTD( operation , __VA_ARGS__ ) 			\
END_DECLARE_RESPLINK_ITFC()


namespace wheels
{
namespace dm
{
    template< typename ITFC_TYPE >
	class rspsLink
	{
	public:
		using itfc_t = typename std::remove_pointer< typename std::decay< ITFC_TYPE >::type >::type;
        static_assert( std::is_base_of< rspsprivate__::respItfc__ ,  itfc_t >::value , "" );
        
        using link_t 		= std::list<  itfc_t* >;
        using iterator 		= typename link_t::iterator;
	protected:
        link_t             m_link__;
		std::mutex         m_mutex__;
	public:
        rspsLink(){}
		virtual ~rspsLink(){}
		/**
		 * @brief 以责任链模式执行的时候接口函数返回false则停止继续传递
		 * @tparam Params 请求的参数类型表
		 * @param params 参数内容
		*/
		template< typename ...Params >
        void request( Params&&... params ){
            for( auto item : m_link__ ){
				std::lock_guard< std::mutex > lck( m_mutex__ );
				auto * p = item ;
				if( p == nullptr ) continue;
				
                bool rst = p->operation( std::forward<Params>( params)...);
                if( rst == false ){
                    break;
                }
            }
        }

		/**
		 * @brief 以责任链模式执行的时候接口函数返回false则停止继续传递。这个方法用于需要使用回调函数针对
		 *    每一个责任链上的负责者进行精细化处理的情况。使用自定义接口的时候，使用宏定义自己的接口或者多个
		 *    接口，就必须使用这个方法执行请求
		 * @tparam Params 请求的参数类型表。
		 * @param fun[ I ], 回调处理函数，函数原型为
		 *		bool func( itfc_t * resp , params... )
		 * @param params 参数内容
		*/
		template< typename Func_t , typename... Params >
		void requestCallback( Func_t && fun , Params&& ...args ){
			using result_type = typename std::result_of< Func_t( itfc_t* , Params&&... ) >::type;
			static_assert( std::is_same<result_type , bool >::value , "" );
			
			for( auto item : m_link__ ){
				std::lock_guard< std::mutex > lck( m_mutex__ );
				auto * p =  item;
				if( p == nullptr ) continue;
				
				bool rst = fun( p , std::forward<Params>(args)... );
				if( rst == false ){
                    break;
                }
			}
		}
		/**
		 * @brief 在最后添加新的处理对象
		 * @tparam subType 对象类型。对象类型必须是rspsprivate__::respItfc__的子类。当对象类型不是继承自rspsprivate__::respItfc__
		 *     在编译过程中会报出错误
		 * @param rsps[ I ], 要添加对象指针
		 * @warning 责任链模式对象并不会管理上所有处理对象的内存情况，如果需要释放对象需要在外部执行释放操作
		*/
        template< typename subType >
        void push_back(  subType * rsps ){
			using type = typename std::remove_pointer< typename std::decay<subType>::type > :: type;
            static_assert( std::is_base_of<rspsprivate__::respItfc__ , type >::value , "" );
			std::lock_guard< std::mutex > lck( m_mutex__ );
            m_link__.push_back( rsps );
        }

		/**
		 * @brief 插入责任对象
		 */
		template< typename subType >
		void insert( iterator it , subType * rsps ){
			using type = typename std::remove_pointer< typename std::decay<subType>::type > :: type;
            static_assert( std::is_base_of<rspsprivate__::respItfc__ , type >::value , "" );
			std::lock_guard< std::mutex > lck( m_mutex__ );
            m_link__.insert( it , rsps );
		}
		/**
		 * @brief 删除链上的一个对象。删除链中间的对象不会影响连上传递过程
		 * @param it[ I ], 要删除的迭代器
		 */
		void erase( iterator it ){
			std::lock_guard< std::mutex > lck( m_mutex__ );
	
            m_link__.erase( it );
		}
		/**
		 * @brief 删除链上的多个对象， 删除[start, end)区间的内容。删除链中间的对象不会影响连上传递过程
		 * @param start , end[ I ], 要删除的迭代器
		 */
		void erase( iterator start , iterator end ){
			std::lock_guard< std::mutex > lck( m_mutex__ );
            m_link__.erase( start , end );
		}

        iterator begin(){ 
			std::lock_guard< std::mutex > lck( m_mutex__ );
			return m_link__.begin(); 
		}
        iterator end(){ 
			std::lock_guard< std::mutex > lck( m_mutex__ );
			return m_link__.end(); 
		}
		
	};
}}
